2.2 DartVM 初始化

runtime/vm/dart.cc 的 DartInit 方法负责 DartVM 的初始化。

方法签名:

char* Dart::DartInit(const Dart_InitializeParams* params) {

这个方法接受一个 Dart_InitializeParams 结构体指针作为参数,返回一个字符串指针(用于返回错误信息)。


VM 标志初始化检查

检查 VM 标志是否已初始化,以及 VM isolate 是否已经存在。这两个条件都会导致初始化失败。

if Initialized() {
  return Utils::StrDup("VM initialization failed-VM Flags not initialized.");
}
if (vm_isolate_ != nullptr) {
  return Utils::StrDup("VM initialization is in an inconsistent state.");
}

snapshot_data 按需加载

如果提供了 VM snapshot 数据,则设置 snapshot。

const Snapshot* snapshot = nullptr;
if (params->vm_snapshot_data != nullptr) {
  snapshot = Snapshot::SetupFromBuffer(params->vm_snapshot_data);
  if (snapshot == nullptr) {
    return Utils::StrDup("Invalid vm isolate snapshot seen");
  }
}

如果有 snapshot,则从 snapshot 中初始化全局 VM 标志。

if (snapshot != nullptr) {
  char* error =
      SnapshotHeaderReader::InitializeGlobalVMFlagsFromSnapshot(snapshot);
  if (error != nullptr) {
    return error;
  }
}

初始化帧布局

初始化帧布局,设置线程启动和退出回调,设置文件操作回调,设置熵源回调,初始化操作系统相关功能。

FrameLayout::Init();

set_thread_start_callback(params->thread_start);
set_thread_exit_callback(params->thread_exit);
SetFileCallbacks(params->file_open, 
				 params->file_read, 
				 params->file_write,
                 params->file_close);
set_entropy_source_callback(params->entropy_source);
OS::Init();

代码观察器

在非产品模式下初始化代码观察器,记录启动时间。

NOT_IN_PRODUCTInit();
if (params->code_observer != nullptr) {
  NOT_IN_PRODUCTRegisterExternal(*params->code_observer);
}
start_time_micros_ = OS::GetCurrentMonotonicMicros();

虚拟内存

初始化虚拟内存系统,对于 Fuchsia 操作系统有特殊处理。

#if defined(DART_HOST_OS_FUCHSIA)
VirtualMemory::Init(params->vmex_resource);
#else
VirtualMemory::Init();
#endif

DartVM 子系统初始化

这一大段代码初始化了 DartVM 的各个子系统,包括操作系统线程、随机数生成器、内存分配器(Zone)、时间线、Isolate 组、Isolate、用户标签、端口映射、服务、自由列表元素、ForwardingCorpse、API、本地符号解析器、展开记录平台、页面、存储缓冲区、标记栈、目标 CPU 特性、FFI 回调元数据等。

OSThread::Init();
Random::Init();
Zone::Init();
#if defined(SUPPORT_TIMELINE)
Timeline::Init();
TimelineBeginEndScope tbesGetVMStream(), "Dart::Init";
#endif
IsolateGroup::Init();
Isolate::InitVM();
UserTags::Init();
PortMap::Init();
Service::Init();
FreeListElement::Init();
ForwardingCorpse::Init();
Api::Init();
NativeSymbolResolver::Init();
UnwindingRecordsPlatform::Init();
Page::Init();
StoreBuffer::Init();
MarkingStack::Init();
TargetCPUFeatures::Init();
FfiCallbackMetadata::Init();

模拟器

如果使用模拟器,则初始化模拟器。

#if defined(USING_SIMULATOR)
Simulator::Init();
#endif

线程池

创建预定义句柄和线程池。

predefined_handles_ = new ReadOnlyHandles();
thread_pool_ = new ThreadPool();

VM isolate

这一大段代码是初始化 VM isolate 的核心逻辑。它创建了 VM isolate,设置了它的标志,创建了堆,注册了 isolate 组,初始化了对象系统,读取了 VM snapshot(如果有的话),并完成了最后的初始化和验证步骤。

{
  // 确保 VM isolate 还未被创建
  ASSERT(vm_isolate_ == nullptr);
  // 确保 VM 标志已经被初始化
  ASSERTInitialized();
  // 标记这是 VM isolate
  const bool is_vm_isolate = true;

  // 初始化 isolate 标志
  Dart_IsolateFlags api_flags;
  Isolate::FlagsInitialize(&api_flags);
  // 设置为系统 isolate
  api_flags.is_system_isolate = true;

  // 创建 IsolateGroupSource,包含 VM isolate 的基本信息
  std::unique_ptr<IsolateGroupSource> source(
	  new IsolateGroupSource(
	      kVmIsolateName, 
	      kVmIsolateName, 
	      params->vm_snapshot_data,
	      params->vm_snapshot_instructions, 
	      nullptr, 
	      -1, 
	      api_flags));
  
  // 创建 IsolateGroup,这是 VM isolate 所属的组
  auto group = new IsolateGroup(
	  std::move(source), 
	  /*embedder_data=*/nullptr,
	  /*object_store=*/nullptr, 
	  api_flags);
  
  // 为 VM isolate 创建堆
  group->CreateHeap(
	  /*is_vm_isolate=*/true,
	  /*is_service_or_kernel_isolate=*/false);
  
  // 注册 IsolateGroup
  IsolateGroup::RegisterIsolateGroup(group);
  
  // 初始化 VM isolate
  vm_isolate_ =
      Isolate::InitIsolate(
	      kVmIsolateName, 
	      group, 
	      api_flags, 
	      is_vm_isolate);
  
  // 标记初始化成功
  group->set_initial_spawn_successful();

  // 验证当前执行环境确实是 VM isolate
  ASSERT(vm_isolate_ == Isolate::Current());
  ASSERT(vm_isolate_ == Thread::Current()->isolate());

  // 获取当前线程
  Thread* T = Thread::Current();
  ASSERT(T != nullptr);
  
  // 创建栈区域和句柄作用域
  StackZone zone(T);
  HandleScope handle_scope(T);
  
  // 初始化 null 和 bool 对象
  Object::InitNullAndBool(vm_isolate_->group());
  
  // 设置对象存储
  vm_isolate_->isolate_group_->set_object_store(new ObjectStore());
  vm_isolate_->isolate_object_store()->Init();
  
  // 初始化终结器
  vm_isolate_->finalizers_ = GrowableObjectArray::null();
  
  // 初始化对象系统
  Object::Init(vm_isolate_->group());
  
  // 初始化偏移表、参数描述符和 IC 数据
  OffsetsTable::Init();
  ArgumentsDescriptor::Init();
  ICData::Init();

  // 如果提供了 VM snapshot 数据
  if (params->vm_snapshot_data != nullptr) {
    // 开始读取 VM snapshot 的时间记录(仅在支持时间线的情况下)
#if defined(SUPPORT_TIMELINE)
    TimelineBeginEndScope tbesGetVMStream(), "ReadVMSnapshot";
#endif
    ASSERT(snapshot != nullptr);
    // 记录 snapshot 类型
    vm_snapshot_kind_ = snapshot->kind();

    // 如果 snapshot 包含代码
    if IncludesCode(vm_snapshot_kind_) {
      // 对于 AOT 编译的 snapshot,JIT 运行时无法处理
      if (vm_snapshot_kind_ == Snapshot::kFullAOT) {
#if !defined(DART_PRECOMPILED_RUNTIME)
        return Utils::StrDup("JIT runtime cannot run a precompiled snapshot");
#endif
      }
      // 确保提供了指令 snapshot
      if (params->vm_snapshot_instructions == nullptr) {
        return Utils::StrDup("Missing instructions snapshot");
      }
    } else if IsFull(vm_snapshot_kind_) {
      // 预编译运行时需要预编译的 snapshot
#if defined(DART_PRECOMPILED_RUNTIME)
      return Utils::StrDup(
          "Precompiled runtime requires a precompiled snapshot");
#else
      // 初始化存根代码和完成对象初始化
      StubCode::Init();
      Object::FinishInit(vm_isolate_->group());
#endif
    } else {
      return Utils::StrDup("Invalid vm isolate snapshot seen");
    }

    // 读取 VM snapshot
    FullSnapshotReader reader(snapshot, params->vm_snapshot_instructions, T);
    const Error& error = Error::Handle(reader.ReadVMSnapshot());
    if (!error.IsNull()) {
      return Utils::StrDup(error.ToErrorCString());
    }

    // 完成对象初始化
    Object::FinishInit(vm_isolate_->group());

    // 记录 snapshot 大小和堆大小(仅在支持时间线的情况下)
#if defined(SUPPORT_TIMELINE)
    if (tbes.enabled()) {
      tbes.SetNumArguments(2);
      tbes.FormatArgument(0, "snapshotSize", "%" Pd, snapshot->length());
      tbes.FormatArgument(
          1, "heapSize", "%" Pd,
          vm_isolate_groupkOld) * kWordSize;
    }
#endif  // !defined(PRODUCT)

    // 如果开启了 isolate 跟踪,打印相关信息
    if (FLAG_trace_isolates) {
      OS::PrintErr("Size of vm isolate snapshot = %" Pd "\n",
                   snapshot->length());
      vm_isolate_group()->heap()->PrintSizes();
      MegamorphicCacheTable::PrintSizes(T);
      intptr_t size;
      intptr_t capacity;
      Symbols::GetStats(vm_isolate_->group(), &size, &capacity);
      OS::PrintErr("VM Isolate: Number of symbols : %" Pd "\n", size);
      OS::PrintErr("VM Isolate: Symbol table capacity : %" Pd "\n", capacity);
    }
  } else {
    // 如果没有提供 VM snapshot 数据
#if defined(DART_PRECOMPILED_RUNTIME)
    return Utils::StrDup(
        "Precompiled runtime requires a precompiled snapshot");
#else
    // 设置 snapshot 类型为 None,初始化存根代码和符号
    vm_snapshot_kind_ = Snapshot::kNone;
    StubCode::Init();
    Object::FinishInit(vm_isolate_->group());
    Symbols::Init(vm_isolate_->group());
#endif
  }

  // 初始化 VM 常量
  T->InitVMConstants();

  // 对于 IA32 或 X64 架构,检查是否支持 SSE2
#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
  if sse2_supported() {
    return Utils::StrDup("SSE2 is required.");
  }
#endif

  // 完成 VM isolate 的最终初始化
  {
#if defined(SUPPORT_TIMELINE)
    TimelineBeginEndScope tbesGetVMStream(), "FinalizeVMIsolate";
#endif
    Object::FinalizeVMIsolate(vm_isolate_->group());
  }

  // 在调试模式下验证堆
#if defined(DEBUG)
  vm_isolate_groupDartInit", kRequireMarked;
#endif
}

Snapshot 类型校验

在 DartVM 的初始化过程中,对 snapshot 类型的判断是非常重要的,因为它决定了 VM 如何加载和执行代码。

Snapshot 概念:Snapshot 是 Dart 程序状态的序列化表示。它可以包含对象图、代码等,用于快速启动和执行 Dart 程序。

Snapshot 类型:

主要有以下几种类型:

在上一节的 Snapshot 校验环节中,代码的逻辑如下:

a. 检查 snapshot 是否包含代码:

b. 如果 snapshot 是完整的(Full),但不包含代码:

c. 如果既不包含代码也不是完整的 snapshot,报错

JIT vs AOT:

为什么需要这些判断:


收尾工作

最后的这段代码完成了一些收尾工作:

  1. 在非产品模式下初始化分析器。
  2. 初始化 API 句柄。
  3. 退出 VM isolate。
  4. 设置各种回调函数。
  5. 在非产品模式下设置服务相关的回调。
  6. 如果不是 AOT 预编译器且需要支持服务或者不是预编译运行时,则运行服务 isolate。
  7. 在非预编译运行时模式下,如果需要启动内核 isolate,则初始化内核 isolate 的状态。

最后,如果一切正常,返回 nullptr 表示初始化成功。

NOT_IN_PRODUCTInit();
Api::InitHandles();

Thread::ExitIsolate();
Isolate::SetCreateGroupCallback(params->create_group);
Isolate::SetInitializeCallback_(params->initialize_isolate);
Isolate::SetShutdownCallback(params->shutdown_isolate);
Isolate::SetCleanupCallback(params->cleanup_isolate);
Isolate::SetGroupCleanupCallback(params->cleanup_group);
Isolate::SetRegisterKernelBlobCallback(params->register_kernel_blob);
Isolate::SetUnregisterKernelBlobCallback(params->unregister_kernel_blob);

#ifndef PRODUCT
const bool support_service = true;
Service::SetGetServiceAssetsCallback(params->get_service_assets);
#else
const bool support_service = false;
#endif

const bool is_dart2_aot_precompiler =
    FLAG_precompiled_mode && !kDartPrecompiledRuntime;

if (!is_dart2_aot_precompiler &&
    (support_service || !kDartPrecompiledRuntime)) {
  ServiceIsolate::Run();
}

#ifndef DART_PRECOMPILED_RUNTIME
if (params->start_kernel_isolate) {
  KernelIsolate::InitializeState();
}
#endif  // DART_PRECOMPILED_RUNTIME

return nullptr;

本文作者:Maeiee

本文链接:2.2 DartVM 初始化

版权声明:如无特别声明,本文即为原创文章,版权归 Maeiee 所有,未经允许不得转载!


喜欢我文章的朋友请随缘打赏,鼓励我创作更多更好的作品!